package beautiful.butterfly.drds.binlog.command;


import beautiful.butterfly.drds.binlog.connection.ConnectionAttributes;
import beautiful.butterfly.drds.binlog.netty.server.NioSocketChannelExtend;
import beautiful.butterfly.drds.binlog.type.ClientCapabilitiesType;
import beautiful.butterfly.drds.binlog.utils.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AuthenticateCommand
{


    private String scramble;
    private int collation;

    public AuthenticateCommand(String scramble, int collation)
    {
        this.scramble = scramble;
        this.collation = collation;
    }

    public void write(ChannelHandlerContext channelHandlerContext)
    {
        // LoggerUtils.debug(logger, "AuthenticateCommand");
        // 准备第一部分
        int clientCapabilities = ClientCapabilitiesType.long_flag | ClientCapabilitiesType.protocol_41
                | ClientCapabilitiesType.secure_connection;
        byte[] clientCapabilitiesBytes = ByteUtils.writeInt(clientCapabilities, 4);
        // 准备第二部分
        int maxLength = 0;
        byte[] maxLengthBytes = ByteUtils.writeInt(maxLength, 4);
        // 准备第三部分
        byte[] collationBytes = ByteUtils.writeInt(this.collation, 1);
        // 准备第4部分
        byte[] zeroBytes = ByteUtils.writeInt(0, 23);
        // 第5部分，写用户名
        ConnectionAttributes connectionAttributes = ((NioSocketChannelExtend) channelHandlerContext.channel()).getConnectionAttributes();
        // ConnectionAttributes myAttribute =
        // context.channel().attr(Constants.MY_CONTEXT_ATTRIBUTES).get();
        String username = connectionAttributes.getUsernameForReplication();
        byte[] usernameBytes = ByteUtils.writeString(username);
        // 第6部分，准备密码
        byte[] lengthBytes = new byte[1];
        byte[] passwordBytes = null;
        String password = connectionAttributes.getPasswordForReplication();
        if (null == password || password.trim().length() == 0)
        {
            passwordBytes = new byte[0];// 空的
        } else
        {
            passwordBytes = ByteUtils.passwordCompatibleWithMySQL411(password, scramble);

        }
        lengthBytes[0] = (byte) passwordBytes.length;
        // 构造总的数据
        int totalCount = 0;
        totalCount += clientCapabilitiesBytes.length;
        totalCount += maxLengthBytes.length;
        totalCount += collationBytes.length;
        totalCount += zeroBytes.length;
        totalCount += usernameBytes.length;
        totalCount += lengthBytes.length;// 长度以一个字节发出去
        totalCount += passwordBytes.length;
        byte[] totalCountBytes = ByteUtils.writeInt(totalCount, 3);
        byte[] commandTypeBytes = new byte[1];
        commandTypeBytes[0] = 1;// 对于验证命令，这里就是1,其它都是0
        // 所有内容串联起来
        ByteBuf byteBuf = Unpooled.buffer(totalCount + 4);
        log.info("---buffer---:" + byteBuf);
        byteBuf.writeBytes(totalCountBytes);
        byteBuf.writeBytes(commandTypeBytes);
        byteBuf.writeBytes(clientCapabilitiesBytes);
        byteBuf.writeBytes(maxLengthBytes);
        byteBuf.writeBytes(collationBytes);
        byteBuf.writeBytes(zeroBytes);
        byteBuf.writeBytes(usernameBytes);
        byteBuf.writeBytes(lengthBytes);
        byteBuf.writeBytes(passwordBytes);
        // 发射
        channelHandlerContext.channel().writeAndFlush(byteBuf);// 缓存清理
        // finalBuf.release();//最终使用者负责释放了，不用担心
    }

}
